package com.meida.module.arc.provider.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.utils.ApiAssert;
import com.meida.module.arc.client.entity.ArcCategory;
import com.meida.module.arc.client.entity.ArcInfo;
import com.meida.module.arc.client.entity.ArcRefRecord;
import com.meida.module.arc.provider.mapper.ArcRefRecordMapper;
import com.meida.module.arc.provider.service.ArcCategoryService;
import com.meida.module.arc.provider.service.ArcInfoService;
import com.meida.module.arc.provider.service.ArcRefRecordService;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.model.ResultBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.mybatis.query.CriteriaQuery;
import org.springframework.transaction.annotation.Propagation;
import com.meida.common.mybatis.query.CriteriaSave;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 关联记录接口实现类
 *
 * @author flyme
 * @date 2022-09-05
 */
@Service
@Transactional(rollbackFor = Exception.class)
@DS("sharding")
public class ArcRefRecordServiceImpl extends BaseServiceImpl<ArcRefRecordMapper, ArcRefRecord> implements ArcRefRecordService {

    @Autowired
    private ArcCategoryService arcCategoryService;

    @Autowired
    private ArcInfoService arcInfoService;

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, ArcRefRecord arr, EntityMap extra) {
        return ResultBody.ok();
    }



    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<ArcRefRecord> cq, ArcRefRecord arr, EntityMap requestMap) {
      cq.orderByDesc("arr.createTime");
      return ResultBody.ok();
    }

    @Override
    public ResultBody getArcRefStatistics(Map param) {
        EntityMap map = new EntityMap(param);
        Long arcInfoId = map.getLong("arcInfoId");
        Long qzId = map.getLong("qzId");
        Long categoryId = map.getLong("categoryId");
        ApiAssert.isNotEmpty("档案id不能为空",arcInfoId);
        ApiAssert.isNotEmpty("全宗id不能为空",qzId);
        ApiAssert.isNotEmpty("门类id不能为空",categoryId);

        QueryWrapper<ArcRefRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ArcRefRecord::getSrcArcInfoId,arcInfoId)
//                .eq(ArcRefRecord::getRefType,1)
                .groupBy(ArcRefRecord::getTargetCategoryId);
        queryWrapper.select("count(targetArcInfoId) as arcInfoCount","max(targetCategoryName) as categoryName","max(targetCategoryType) as categoryType","targetCategoryId as categoryId");
        List<Map<String, Object>> list = this.listMaps(queryWrapper);
        int arcInfoCount = 0;
        Map result = new HashMap();
        result.put("categoryCount",list.size());
        for(Map<String,Object> item:list){
            Object obj = item.get("arcInfoCount");
            if(FlymeUtils.isNotEmpty(obj)){
                arcInfoCount += Integer.parseInt(obj.toString());
            }
        }

        result.put("arcInfoCount",arcInfoCount);
        result.put("categoryList",list);
        return ResultBody.ok(result);
    }

    @Override
    public ResultBody batchSave(Map param) {
        EntityMap map = new EntityMap(param);
        Long srcArcInfoId = map.getLong("srcArcInfoId");
        Long srcCategoryId = map.getLong("srcCategoryId");
        Long targetCategoryId = map.getLong("targetCategoryId");
        String targetArcInfoIds = map.get("targetArcInfoIds");
        Long qzId = map.getLong("qzId");
        ApiAssert.isNotEmpty("全宗id不能为空",qzId);
        ApiAssert.isNotEmpty("主关联档案不能为空",srcArcInfoId);
        ApiAssert.isNotEmpty("主关联门类不能为空",srcCategoryId);
        ApiAssert.isNotEmpty("被关联门类不能为空",targetCategoryId);
        ApiAssert.isNotEmpty("被关联档案不能为空",targetArcInfoIds);
        //每条关联生成两条数据，  一个为主关联数据，一个为被关联数据
        String[] targetArcInfoIdsArr = targetArcInfoIds.split(",");
        if(targetArcInfoIdsArr==null||targetArcInfoIdsArr.length<=0){
            ApiAssert.failure("被关联档案不饿能为空");
        }
        ArcCategory srcCategory = arcCategoryService.getById(srcCategoryId);
        ArcCategory targetCategory = arcCategoryService.getById(targetCategoryId);
        //查询被关联档案是否已经关联过
        Long count = this.count(new QueryWrapper<ArcRefRecord>().lambda()
                .eq(ArcRefRecord::getSrcArcInfoId, srcArcInfoId)
                .in(ArcRefRecord::getTargetArcInfoId, Arrays.stream(targetArcInfoIdsArr).map(item->{
                    return Long.parseLong(item);
                }).collect(Collectors.toList())));
        if(count==null){
            count = 0L;
        }


        //1，添加关联数据
        //2，更新主关联和被关联档案关联数量
        List<ArcRefRecord> refRecords = new ArrayList<>();
        Arrays.stream(targetArcInfoIdsArr).distinct().map(item->{
            return Long.parseLong(item);
        }).forEach(item->{
            //不允许自关联
            if(!item.equals(srcArcInfoId)) {
                //1校验当前主关联与被关联是否已关联，如果已关联则删除，防止关联多次
                this.remove(new QueryWrapper<ArcRefRecord>().lambda()
                        .eq(ArcRefRecord::getSrcArcInfoId, srcArcInfoId)
                        .eq(ArcRefRecord::getTargetArcInfoId, item));
                //2删除被关联
                this.remove(new QueryWrapper<ArcRefRecord>().lambda()
                        .eq(ArcRefRecord::getTargetArcInfoId, srcArcInfoId)
                        .eq(ArcRefRecord::getSrcArcInfoId, item));
                Long refNo = IdWorker.getId();
                //3添加主关联
                refRecords.add(new ArcRefRecord().setRefType(1)
                        .setSrcCategoryId(srcCategoryId)
                        .setSrcCategoryName(srcCategory.getCnName())
                        .setSrcCategoryType(srcCategory.getType())
                        .setTargetCategoryId(targetCategoryId)
                        .setTargetCategoryName(targetCategory.getCnName())
                        .setTargetCategoryType(targetCategory.getType())
                        .setSrcArcInfoId(srcArcInfoId)
                        .setTargetArcInfoId(item)
                        .setRefNo(refNo));
                //4添加被关联
                refRecords.add(new ArcRefRecord().setRefType(2)
                        .setSrcCategoryId(targetCategoryId)
                        .setSrcCategoryName(targetCategory.getCnName())
                        .setSrcCategoryType(targetCategory.getType())
                        .setTargetCategoryId(srcCategoryId)
                        .setTargetCategoryName(srcCategory.getCnName())
                        .setTargetCategoryType(srcCategory.getType())
                        .setSrcArcInfoId(item)
                        .setTargetArcInfoId(srcArcInfoId)
                        .setRefNo(refNo));
            }
        });
        this.saveBatch(refRecords);
        refRecords.stream().filter(item->{
            //过滤所有被关联档案
            return item.getRefType()==2;
        }).forEach(item->{
            //被关联档案重新计算关联数量
            caculateArcRefCount(item.getSrcArcInfoId(),item.getSrcCategoryId());
        });
        //主关联档案重新计算关联数量
        caculateArcRefCount(srcArcInfoId,srcCategoryId);
        Map result = new HashMap();
        result.put("successCount",targetArcInfoIdsArr.length-count);
        result.put("hasRefCount",count);
        return ResultBody.ok(result);
    }

    @Override
    public ResultBody clearRef(Map param) {
        EntityMap map = new EntityMap(param);
        String srcArcInfoIds = map.get("srcArcInfoIds");
        Long srcCategoryId = map.getLong("srcCategoryId");
        Long qzId = map.getLong("qzId");
        ApiAssert.isNotEmpty("全宗id不能为空",qzId);
        ApiAssert.isNotEmpty("档案不能为空",srcArcInfoIds);
        ApiAssert.isNotEmpty("门类不能为空",srcCategoryId);
        String[] srcArcInfoIdsArr = srcArcInfoIds.split(",");
        if(srcArcInfoIdsArr==null||srcArcInfoIdsArr.length<=0){
            ApiAssert.failure("被关联档案不饿能为空");
        }
        Long targetCategoryId = map.getLong("targetCategoryId");
        boolean partFlag = false;
        String[] targetArcInfoIdsArr = null;
        if(FlymeUtils.isNotEmpty(targetCategoryId)){
            String targetArcInfoIds = map.get("targetArcInfoIds");
            ApiAssert.isNotEmpty("被清除关联档案为空",targetArcInfoIds);
            targetArcInfoIdsArr = targetArcInfoIds.split(",");
            if(targetArcInfoIdsArr.length<=0){
                ApiAssert.failure("被清除关联档案为空");
            }
            partFlag = true;
        }
        QueryWrapper<ArcRefRecord> queryWrapper = new QueryWrapper<ArcRefRecord>();
        queryWrapper.lambda()
                .in(ArcRefRecord::getSrcArcInfoId, Arrays.stream(srcArcInfoIdsArr).map(item->{
                    return Long.parseLong(item);
                }).collect(Collectors.toList()));
        if(partFlag){
            queryWrapper.lambda().eq(ArcRefRecord::getTargetCategoryId,targetCategoryId)
                    .in(ArcRefRecord::getTargetArcInfoId,Arrays.stream(targetArcInfoIdsArr).map(item->{
                        return Long.parseLong(item);
                    }).collect(Collectors.toList()));
        }
        List<ArcRefRecord> list = this.list(queryWrapper);
        list.stream().forEach(item->{
            this.remove(new QueryWrapper<ArcRefRecord>().lambda()
                    .eq(ArcRefRecord::getRefNo, item.getRefNo()));
        });
        //重新计算所有主关联数量
        Arrays.stream(srcArcInfoIdsArr).forEach(item->{
            caculateArcRefCount(Long.parseLong(item),srcCategoryId);
        });
        //重新计算所有被关联数量
        list.forEach(item->{
            caculateArcRefCount(item.getTargetArcInfoId(),item.getTargetCategoryId());
        });
        return ResultBody.ok();
    }

    @Override
    public void caculateArcRefCount(Long arcInfoId,Long categoryId){
        Long count = this.count(new QueryWrapper<ArcRefRecord>().lambda().eq(ArcRefRecord::getSrcArcInfoId,arcInfoId));
        UpdateWrapper<ArcInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(ArcInfo::getArcInfoId,arcInfoId)
                .eq(ArcInfo::getCategoryId,categoryId)
                .set(ArcInfo::getRefCount,count);
        this.arcInfoService.update(updateWrapper);
    }
}
